/**
 * HEIG-VD
 * MCR - Projet "Pandemie"
 * Auteurs: Thierry Forchelet, Louis Jaquier, Grégory Moinat, Julien Rebetez
 */
package visitable;

import visitors.Visitor;

import java.util.LinkedList;
import java.util.Queue;

/**
 * Gestionnaire de propagation des maladies
 * Il s'agit d'un singleton
 */
public class SpreadManager {
   /**
    * Représente une propagation d'un visiteur sur une connection en provenance d'une créature
    */
   private class Spread {
      private Creature from;
      private CreatureConnection conn;
      private Visitor v;
      
      private Spread(Creature from, CreatureConnection conn, Visitor v) {
         this.from = from;
         this.conn = conn;
         this.v = v;
      }
   }
   
  private static SpreadManager instance;
  // Queue des propagations en attente
  private Queue<Spread> spreads = new LinkedList<Spread>();
  
  private SpreadManager() {
     // Thread pour le traitement des propagations en attente
     new Thread() {
        public void run() {
           Spread spread;
           while(true) {
              synchronized(spreads) {
                 if(spreads.isEmpty())
                     try {
                        spreads.wait();
                     } catch (InterruptedException e) {
                        e.printStackTrace();
                     }
                 spread = spreads.remove();
              }
              spread.conn.spread(spread.from, spread.v);
           }
        }
     }.start();
  }
  
  public static SpreadManager getInstance() {
    if (instance == null)
      instance = new SpreadManager();
    return instance;
  }
  
  /**
   * Supprime les maladies en train d'être propagées
   */
  public void clear () {
    synchronized(spreads) {
      spreads.clear();
    }
  }
  
  /**
   * Ajoute une nouvelle propagation
   * @param from la source de la propagation
   * @param conn la connexion par ou passe la propagation
   * @param v le visiteur a propager
   */
  public void addSpread(Creature from, CreatureConnection conn, Visitor v) {
     synchronized(spreads) {
        spreads.add(new Spread(from, conn, v));
        spreads.notify();
     }
  }
}
